#include "music_settings.h"

#include <QTextStream>
#include <QRegExp>

MusicSettings::MusicSettings() {
  initialize();
}

/*!
 * Initialise la configuration avec les paramètres par défaut
 */
void MusicSettings::initialize() {
  scoreSize = 16;
  nbOctave = 1;
  tempo = MODERATO;
  scale = UNDEFINED_SCALE;
  mode = UNDEFINED_MODE;
  firstNote = UNDEFINED_DEGREE;
  pattern = "";
  conjoint = false;
  noRepetition = false;
}

/*!
 * Écrit les paramètres dans un flux
 */
void MusicSettings::write(QTextStream& out) {
  out << scoreSize    << "\n"
      << nbOctave     << "\n"
      << tempo        << "\n"
      << scale        << "\n"
      << mode         << "\n"
      << firstNote    << "\n"
      << pattern      << "$\n" // $ pour marquer la fin du motif
      << conjoint     << "\n"
      << noRepetition << "\n";
}

/*!
 * Lit les paramètres à partir du flux
 */
void MusicSettings::read(QTextStream& in) {
  /*
   * Lecture non sécurisée
   * La lecture de fichiers invalides ou corrompus
   * peut mener à des comportements non attendus
   */
  int tmp;

  in >> scoreSize;
  in >> nbOctave;

  in >> tmp;
  tempo = (Tempo) tmp;

  in >> tmp;
  scale = (Scale) tmp;

  in >> tmp;
  mode = (Mode) tmp;

  in >> tmp;
  firstNote = (Degree) tmp;

  in >> pattern;
  pattern.remove(QRegExp("\\$$"));

  in >> tmp;
  conjoint = (bool) tmp;

  in >> tmp;
  noRepetition = (bool) tmp;
}

/*!
 * Convertit le mode en chaîne de caractères
 */
QString MusicSettings::modeToString(Mode mode) {
  switch(mode) {
    case MAJOR:
      return "major";
    case MINOR:
      return "minor";
    case UNDEFINED_MODE:
      return "";
    default:
      return NULL;
  }
}

/*!
 * Convertit le mode en chaîne de caractères (utilisable dans l'interface)
 */
QString MusicSettings::modeToHumanString(Mode mode) {
  switch(mode) {
    case MAJOR:
      return "Majeur";
    case MINOR:
      return "Mineur";
    case UNDEFINED_MODE:
      return "<font color=\"#aaaaaa\">Non défini</font>";
    default:
      return NULL;
  }
}

/*!
 * Convertit la gamme en chaîne de caractères
 */
QString MusicSettings::scaleToString(Scale scale) {
  switch(scale) {
    case A:
      return "a";
    case B:
      return "b";
    case C:
      return "c";
    case D:
      return "d";
    case E:
      return "e";
    case F:
      return "f";
    case G:
      return "g";
    case AIS:
      return "ais";
    case CIS:
      return "cis";
    case DIS:
      return "dis";
    case FIS:
      return "fis";
    case GIS:
      return "gis";
    case AES:
      return "aes";
    case BES:
      return "bes";
    case CES:
      return "ces";
    case DES:
      return "des";
    case EES:
      return "ees";
    case GES:
      return "ges";
    case UNDEFINED_SCALE:
      return "";
    default:
      return NULL;
  }
}

/*!
 * Convertir la tonalité en chaîne de caractère (utilisable dans l'interface)
 */
QString MusicSettings::scaleToHumanString(Scale scale) {
  switch(scale) {
    case A:
      return "La";
    case B:
      return "Si";
    case C:
      return "Do";
    case D:
      return "Ré";
    case E:
      return "Mi";
    case F:
      return "Fa";
    case G:
      return "Sol";
    case AIS:
      return "La dièse";
    case CIS:
      return "Do dièse";
    case DIS:
      return "Ré dièse";
    case FIS:
      return "Fa dièse";
    case GIS:
      return "Sol dièse";
    case AES:
      return "La bémol";
    case BES:
      return "Si bémol";
    case CES:
      return "Do bémol";
    case DES:
      return "Ré bémol";
    case EES:
      return "Mi bémol";
    case GES:
      return "Sol bémol";
    case UNDEFINED_SCALE:
      return "<font color=\"#aaaaaa\">Non défini</font>";
    default:
      return NULL;
  }
}

/*!
 * Convertit le tempo en chaîne de caractères (utilisable dans l'interface)
 */
QString MusicSettings::tempoToHumanString(Tempo tempo) {
  switch(tempo) {
    case LARGO:
      return "Largo - 60";
    case LARGHETTO:
      return "Larghetto - 66";
    case ADAGIO:
      return "Adagio - 76";
    case ANDANTE:
      return "Andante - 108";
    case MODERATO:
      return "Moderato - 120";
    case ALLEGRO:
      return "Allegro - 168";
    case PRESTO:
      return "Presto - 200";
    case PRESTISSIMO:
      return "Prestissimo - 208";
    default:
      return NULL;
  }
}

/*!
 * Convertit le degré en entier
 */
int MusicSettings::degreeToInt(Degree degree, Mode mode) {
  switch(mode) {
    case MAJOR:
      /*
       * La gamme diatonique majeure est une succession de :
       *  - 1 ton   ]
       *  - 1 ton   ] tétracorde inférieur
       *  - 1/2 ton ]
       *  - 1 ton
       *  - 1 ton   ]
       *  - 1 ton   ] tétracorde supérieur
       *  - 1/2 ton ]
       */
      switch(degree) {
        case TONIC:
          return 1;
        case SUPERTONIC:
          return 3;
        case MEDIANT:
          return 5;
        case SUBDOMINANT:
          return 6;
        case DOMINANT:
          return 8;
        case SUBMEDIANT:
          return 10;
        case LEADING:
          return 12;
        default:
          return NULL;
      }
    case MINOR:
      /*
       * La gamme diatonique mineure est une succession de :
       *  - 1 ton
       *  - 1/2 ton
       *  - 1 ton
       *  - 1 ton
       *  - 1/2 ton
       *  - 1 ton + 1/2 ton chromatique
       *  - 1/2 ton
       */
      switch(degree) {
        case TONIC:
          return 1;
        case SUPERTONIC:
          return 3;
        case MEDIANT:
          return 4;
        case SUBDOMINANT:
          return 6;
        case DOMINANT:
          return 8;      
        case SUBMEDIANT: // le demi-ton chromatique (pour la sensible)
          return 9;      // n'est pas pris en compte ici
        case LEADING:    // pour des raisons de simplicité de calcul
          return 11;     //
        default:
          return NULL;
      }
    default:
      return NULL;
  }
}

/*!
 * Convertit le degré en chaîne de caractères (utilisable dans l'interface)
 */
QString MusicSettings::degreeToHumanString(Degree degree) {
  switch(degree) {
    case TONIC:
      return "Tonique - 1";
    case SUPERTONIC:
      return "Sus-tonique - 2";
    case MEDIANT:
      return "Médiante - 3";
    case SUBDOMINANT:
      return "Sous-dominante - 4";
    case DOMINANT:
      return "Dominante - 5";
    case SUBMEDIANT:
      return "Sus-dominante - 6";
    case LEADING:
      return "Sensible - 7";
    case UNDEFINED_DEGREE:
      return "<font color=\"#aaaaaa\">Non défini</font>";
    default:
      return NULL;
  }
}
